package com.ledou44.ledourpc.service;

import com.ledou44.ledourpc.servicehandler.ServiceHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
 * @author ledou44
 */
@Slf4j
@Data
@Component
@ConfigurationProperties(prefix = "ledourpc.service")
public class Service {

    private Integer servicePort = 8888;

    public void run () {
        new Thread(this::doRun).start();
    }

    public void doRun() {
        //创建boss和work两个线程组
        //boss处理连接请求，work处理客户端相关业务逻辑
        EventLoopGroup boss = new NioEventLoopGroup();
        EventLoopGroup work = new NioEventLoopGroup();

        //创建服务器端的启动对象和配置启动参数
        ServerBootstrap bootstrap = new ServerBootstrap();

        //使用链式编程进行设置
        bootstrap.group(boss,work) //设置两个线程组
                //使用NioSocketChannel作为服务器的通道实现
                .channel(NioServerSocketChannel.class)
                //当并发执行的请求达到上限后，该参数意味着能让最多64个请求入队等待执行！
                .option(ChannelOption.SO_BACKLOG,64)
                //设置保持活动连接状态,超过一定时间，服务器将发送探测ack报文
                .childOption(ChannelOption.SO_KEEPALIVE,true)
                //给我们的work的EventLoop对应的管道设置处理器
                .childHandler(new ServiceHandler());

        log.info("**************ledourpc启动成功("+servicePort+")*****************");
        //sync是让该方法不会阻塞在这里，这里每个sync都可以换成await阻塞
        //注意，如果不加后面的channel().closeFuture().sync()，那么程序会直接按顺序执行finally的语句shutdownGracefully()而不会阻塞循环。
        //另外要注意，这个channel().closeFuture().sync()一定要放在try语句的最后一行，否则如果后面还有代码的话都会被忽略，阻塞在当前行等待关闭！
        try {
            ChannelFuture channelFuture = bootstrap.bind(servicePort).sync();
            //对关闭通道进行监听
            channelFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}
